package com.shuai.proxy;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import com.shuai.RpcApplication;
import com.shuai.common.RpcRequest;
import com.shuai.common.RpcResponse;
import com.shuai.common.ServiceMetaInfo;
import com.shuai.config.RpcConfig;
import com.shuai.constants.RpcConstant;
import com.shuai.registry.Registry;
import com.shuai.registry.RegistryFactory;
import com.shuai.serializer.Serializer;
import com.shuai.serializer.SerializerFactory;
import java.io.IOException;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.util.List;

/** 服务代理（JDK 动态代理） */
public class ServiceProxy implements InvocationHandler {

  /**
   * 调用代理
   *
   * @return
   * @throws Throwable
   */
  @Override
  public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    // 指定序列化器
    final Serializer serializer =
        SerializerFactory.getInstance(RpcApplication.getRpcConfig().getSerializer());

    // 构造请求
    String serviceName = method.getDeclaringClass().getName();
    RpcRequest rpcRequest =
        RpcRequest.builder()
            .serviceName(serviceName)
            .methodName(method.getName())
            .parameterTypes(method.getParameterTypes())
            .args(args)
            .build();
    try {
      // 序列化
      byte[] bodyBytes = serializer.serialize(rpcRequest);

      // 从注册中心获取服务提供者请求地址
      RpcConfig rpcConfig = RpcApplication.getRpcConfig();
      Registry registry = RegistryFactory.getInstance(rpcConfig.getRegistryConfig().getRegistry());
      ServiceMetaInfo serviceMetaInfo = new ServiceMetaInfo();
      serviceMetaInfo.setServiceName(serviceName);
      serviceMetaInfo.setServiceVersion(RpcConstant.DEFAULT_SERVICE_VERSION);
      List<ServiceMetaInfo> serviceMetaInfoList =
          registry.serviceDiscovery(serviceMetaInfo.getServiceKey());
      if (CollUtil.isEmpty(serviceMetaInfoList)) {
        throw new RuntimeException("暂无服务地址");
      }
      ServiceMetaInfo selectedServiceMetaInfo = serviceMetaInfoList.get(0);

      // 发送请求
      try (HttpResponse httpResponse =
          HttpRequest.post(selectedServiceMetaInfo.getServiceAddress()).body(bodyBytes).execute()) {
        byte[] result = httpResponse.bodyBytes();
        // 反序列化
        RpcResponse rpcResponse = serializer.deserialize(result, RpcResponse.class);
        return rpcResponse.getData();
      }
    } catch (IOException e) {
      e.printStackTrace();
    }
    return null;
  }
}
